﻿using System;

namespace Dotnet.Utils.Utility.ObjectExtensions.Number
{
    /// <summary>
    /// 数字工具
    /// </summary>
    public static class NumHelper
    {
        #region Round45

        /// <summary>
        /// 四舍五入
        /// </summary>
        /// <param name="d">要舍入的小数。</param>
        /// <param name="decimals">返回值中的有效数字位数（精度）。</param>
        /// <returns>结果</returns>
        public static decimal Round45(decimal d, int decimals)
        {
            return Math.Round(d, decimals, MidpointRounding.AwayFromZero);
        }

        /// <summary>
        /// 四舍五入
        /// </summary>
        /// <param name="value">要舍入的小数。</param>
        /// <param name="digits">返回值中的有效数字位数（精度）。</param>
        /// <returns>结果</returns>
        public static double Round45(double value, int digits)
        {
            return Math.Round(value, digits, MidpointRounding.AwayFromZero);
        }

        #endregion Round45

        #region CeilingUp

        /// <summary>
        /// 取天花板
        /// </summary>
        /// <param name="d">小数。</param>
        /// <returns></returns>
        public static decimal CeilingUp(decimal d)
        {
            if (d > 0)
            {
                return Math.Ceiling(d);
            }
            else
            {
                return -Math.Ceiling(-d);
            }
        }

        /// <summary>
        /// 取天花板
        /// </summary>
        /// <param name="value">双精度浮点数字。</param>
        /// <returns></returns>
        public static double CeilingUp(double value)
        {
            if (value > 0)
            {
                return Math.Ceiling(value);
            }
            else
            {
                return -Math.Ceiling(-value);
            }
        }

        #endregion CeilingUp

        #region FloorDown

        /// <summary>
        /// 取地板
        /// </summary>
        /// <param name="d">小数。</param>
        /// <returns></returns>
        public static decimal FloorDown(decimal d)
        {
            if (d > 0)
            {
                return Math.Floor(d);
            }
            else
            {
                return -Math.Floor(-d);
            }
        }

        /// <summary>
        /// 取地板
        /// </summary>
        /// <param name="value">双精度浮点数字。</param>
        /// <returns></returns>
        public static double FloorDown(double value)
        {
            if (value > 0)
            {
                return Math.Floor(value);
            }
            else
            {
                return -Math.Floor(-value);
            }
        }

        #endregion FloorDown

        /// <summary>
        /// 判断某个数字的大小是否超过了允许的最大值。
        /// </summary>
        /// <param name="fValue"><see cref="decimal"/>，要进行判断的数字。</param>
        /// <param name="iMaxIntLength"><see cref="int"/>，允许的最大整数位大小（小数位超过时Oracle会自动进行截取）。</param>
        /// <returns>超出最大值返回true，否则返回false。</returns>
        public static bool IsOutOfSize(decimal fValue, int iMaxIntLength)
        {
            //说明：此函数主要判断fValue的整数部分是否超出指定的位数。

            //判断iMaxIntLength是否超出十进制的最大位数，这里限制为26位
            if (iMaxIntLength > 26 || iMaxIntLength < 0)
            {
                return true;
            }

            //获取fValue的整数部分的值
            decimal fTruncateValue = Math.Abs(decimal.Truncate(fValue));
            decimal fMaxValue = (decimal)Math.Pow(10d, iMaxIntLength);
            return fTruncateValue >= fMaxValue;

            //todo: 当前判断方法需要改进
            //if(fValue == decimal.MinValue)
            //	return false;
            //string sValue = fValue.ToString();
            //if(sValue.IndexOf(".") > -1)
            //  sValue = sValue.Split('.')[0];
            //return (sValue.Length > iMaxIntSize);
        }
    }
}